`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    07:41:47 06/21/2009 
// Design Name: 
// Module Name:    pong 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------
// 640x480 @ 60Hz, from a 25MHz input clock
// line duration is slightly longer than spec, but 
// number of lines is fewer to compensate
// -----------------------------------------------
module video_timer(
		input clk25,
		output hsyncOut,
		output vsyncOut,
		output [9:0] xposOut,
		output [9:0] yposOut
	);

	reg [9:0] xpos;
	reg [9:0] ypos;

	wire endline = (xpos == 799);

	always @(posedge clk25) begin
		if (endline)
		  xpos <= 0;
		else
		  xpos <= xpos + 1;
	end

	always @(posedge clk25) begin
		if (endline) begin
			if (ypos == 520)
				ypos <= 0;
			else
				ypos <= ypos + 1;	
		end
	end
		 
	reg hsync, vsync;
	always @(posedge clk25) begin
		hsync <= ~(xpos > 664 && xpos <= 759);  // active for 96 clocks
		vsync <= ~(ypos == 490 || ypos == 491);   // active for lines 490 and 491
	end

	assign hsyncOut = hsync;
	assign vsyncOut = vsync;
	assign xposOut = xpos;
	assign yposOut = ypos;

endmodule

// -----------------------------------------------
// updates the ball and paddle positions, and
// determines the output video image
// -----------------------------------------------


module game(input clk25,
				input [9:0] xpos,
				input [9:0] ypos,
				output red,
				output green,
				output blue);

	reg [9:0] circ_pos_x;
	reg [9:0] circ_pos_y;
	reg [9:0] circ_vel_x;
	reg [9:0] circ_vel_y;
	reg [9:0] circ_rad;

	wire endOfFrame = (xpos == 0 && ypos == 440);
		
	always @(posedge clk25) begin
		/*circ_vel_x <= circ_vel_x;
		circ_vel_y <= circ_vel_y;
		circ_pos_x <= circ_pos_x;
		circ_pos_y <= circ_pos_y;
		circ_rad <= 20;*/
		if (endOfFrame) begin
			if(circ_rad==0) begin
				circ_pos_x <= 100;
				circ_pos_y <= 100;
				circ_vel_x <= 3;
				circ_vel_y <= 1;
				circ_rad <= 20;
			end else begin
				circ_vel_x <= circ_vel_x;
				circ_vel_y <= circ_vel_y+1;
				circ_pos_x <= circ_pos_x+circ_vel_x;
				circ_pos_y <= circ_pos_y+circ_vel_y;
				circ_rad <= 20;

				if(circ_pos_x>620) begin
					circ_pos_x <= 620;
					circ_vel_x <= -3;
				end
				if(circ_pos_y>460) begin
					circ_pos_y <= 460;
					circ_vel_y <= -circ_vel_y;
				end
				if(circ_pos_x<circ_rad) begin
					circ_vel_x <= 3;
					circ_pos_x <= circ_rad;
				end
				if(circ_pos_y<circ_rad) begin
					circ_vel_y <= -circ_vel_y;
					circ_pos_y <= circ_rad;
				end
			end
		end
	end
	
	wire inrange = (xpos<640 && ypos<480 && xpos>0 && ypos>0);
	/*reg [9:0] dx;
	reg [9:0] dy;
	
	always@* begin
		if (circ_pos_x>xpos) dx=circ_pos_x-xpos;
		else dx=xpos-circ_pos_x;
		if (circ_pos_y>ypos) dy=circ_pos_y-ypos;
		else dy=ypos-circ_pos_y;		
	end
	wire circ=dx*dx+dy*dy<circ_rad*circ_rad;*/

	wire [21:0] dst=(xpos-circ_pos_x)*(xpos-circ_pos_x)+(ypos-circ_pos_y)*(ypos-circ_pos_y);
	wire [19:0] dst2=circ_rad*circ_rad;
	wire circ=dst<dst2;
	assign red   = 1'b1 && inrange;
	assign green = !circ && inrange;
	assign blue  = 1'b0 && inrange;

endmodule

// -----------------------------------------------
// top-level module
// -----------------------------------------------

module vga(
    input clk50,
    output red,
    output green,
    output blue,
    output hsync,
    output vsync
    );

// divide input clock by two, and use a global 
// clock buffer for the derived clock
reg clk25_int;
always @(posedge clk50) begin
	clk25_int <= ~clk25_int;
end

wire clk25;
BUFG bufg_inst(clk25, clk25_int);

wire [9:0] xpos;
wire [9:0] ypos;

video_timer video_timer_inst(clk25, hsync, vsync, xpos, ypos);
game game_inst(clk25, xpos, ypos, red, green, blue);
					
endmodule
